using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FlatRedBall;
using FlatRedBall.Graphics;
using FlatRedBall.Input;

namespace MiJuego
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class CollisionManager
    {
        List<GameComponentCollision>[] layers;
        List<RuleCollision> rules;

        int nlayers = 10;

        int radius = 1;

        public int NLayer
        {
            get { return nlayers;  }
        }

        static CollisionManager colMgr;

        public CollisionManager()
        {
            layers = new List<GameComponentCollision>[nlayers];
            rules = new List<RuleCollision>();

            for (int i = 0; i < nlayers; ++i)
            {
                layers[i] = new List<GameComponentCollision>();
            }
        }

        /// <summary>
        /// Retorna el manejador de colisiones
        /// </summary>
        /// <returns></returns>
        public static CollisionManager getInstance()
        {
            if (colMgr == null)
                colMgr = new CollisionManager();

            return colMgr;
        }

        /// <summary>
        /// Chequea las colisiones
        /// </summary>
        public void Update()
        {
            foreach (RuleCollision rule in rules)
            {
                List<GameComponentCollision> layer1 = layers[rule.iLayer1];
                List<GameComponentCollision> layer2 = layers[rule.iLayer2];

                foreach (GameComponentCollision gc1 in layer1)
                {
                    if (gc1.alive)
                    {
                        Rectangle r1 = new Rectangle((int)gc1.sprite.X, (int)gc1.sprite.Y, radius, radius);

                        foreach (GameComponentCollision gc2 in layer2)
                        {
                            if (InputManager.Keyboard.KeyDown(Keys.A))
                            {
                                gc1.sprite.X = gc1.sprite.X;
                            }

                            if (gc2.alive)
                            {
                                Rectangle r2 = new Rectangle((int)gc2.sprite.X, (int)gc2.sprite.Y, radius, radius);

                                if (r1.Intersects(r2))
                                {
                                    gc1.Collision(gc2);
                                    gc2.Collision(gc1);

                                    if (gc1.alive)
                                        break;
                                }
                            }
                        }
                    }
                }

            }
        }

        /// <summary>
        /// Adhiere una regla de colision. Entre las capas iLayer1 y iLayer2
        /// </summary>
        /// <param name="iLayer1"></param>
        /// <param name="iLayer2"></param>
        public void AddRuleCollision(int iLayer1, int iLayer2)
        {
            rules.Add(new RuleCollision(iLayer1, iLayer2));
        }

        /// <summary>
        /// Adhiere un componente a la capa de colision de dicho componente
        /// </summary>
        /// <param name="component"></param>
        public void AddComponent(GameComponentCollision component)
        {
            layers[component.iLayerCollision].Add(component);
        }

        /// <summary>
        /// Remueve el componente de la capa de colision en que se encuentra
        /// </summary>
        /// <param name="component"></param>
        public void RemoveComponent(GameComponentCollision component)
        {
            layers[component.iLayerCollision].Remove(component);
        }


        /// <summary>
        /// Representa una clase de regla de colision
        /// </summary>
        public class RuleCollision
        {
            public int iLayer1;
            public int iLayer2;

            public RuleCollision(int iLayer1, int iLayer2)
            {
                this.iLayer1 = iLayer1;
                this.iLayer2 = iLayer2;
            }
        }

    }
}
